/**
 * Copyright (c) 2021-2030, NDWP.
 * <p>
 */
package com.example.waternetwork.api.config;

import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;


/**
 * ControllerLogAspect
 *
 * @ Author     ：Chenyong.
 * @ Date       ：Created in 08:12 2025/6/20
 */
@Aspect
@Component
public class ControllerLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(ControllerLogAspect.class);
    /**
     * 环绕切入所有 Controller 下的方法
     */
    @Around("execution(* com.example..controller..*(..))")
    public Object logAroundController(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取 HttpServletRequest
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attrs != null ? attrs.getRequest() : null;

        String requestId = generateRequestId();
        MDC.put("requestId", requestId);
        String ip = request != null ? getClientIp(request) : "未知";

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
        // 获取参数名与值
        String[] paramNames = signature.getParameterNames();
        Object[] paramValues = joinPoint.getArgs();
        Map<String, Object> paramMap = new LinkedHashMap<>();
        for (int i = 0; i < paramNames.length; i++) {
            paramMap.put(paramNames[i], paramValues[i]);
        }

        long start = System.currentTimeMillis();
        logger.info("[{}] === 请求开始 ===", requestId);
        if (request != null) {
            logger.info("[{}] 请求地址: {} {}", requestId, request.getMethod(), request.getRequestURI());
            logger.info("[{}] 客户端 IP: {}", requestId, ip);
        }
        logger.info("[{}] 调用方法: {}.{}", requestId, className, methodName);
        logger.info("[{}] 请求参数: {}", requestId, paramMap);

        Object result;

        try {
            result = joinPoint.proceed();
        } catch (Throwable t) {
            logger.error("[{}] Controller 执行异常", requestId, t);
            throw t;
        }
        finally {
            MDC.remove("requestId");
        }
        long end = System.currentTimeMillis();
        logger.info("[{}] 请求完成，耗时: {} ms", requestId, end - start);
        logger.info("[{}] 返回结果: {}", requestId, result);
        logger.info("[{}] === 请求结束 ===\n", requestId);
        return result;
    }


    /**
     * 获取客户端 IP 地址，考虑代理转发场景
     */
    private String getClientIp(HttpServletRequest request) {
        String[] headers = {
                "X-Forwarded-For",
                "Proxy-Client-IP",
                "WL-Proxy-Client-IP",
                "HTTP_CLIENT_IP",
                "HTTP_X_FORWARDED_FOR"
        };

        for (String header : headers) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
                // 如果有多个 IP，取第一个
                return ip.split(",")[0].trim();
            }
        }

        return request.getRemoteAddr();
    }

    private String generateRequestId() {
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        String shortUUID = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return timestamp + "-" + shortUUID;
    }
}